package com.dayu.finecomm.iot;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dayu.finecomm.aop.ClassLevelAnnotation;
import com.dayu.finecomm.aop.MethodLevelAnnotation;
import com.dayu.finecomm.iot.ssl.SslContextFactory;

/**
 * IotHttpClientUtil 同步获取响应
 * 
 * @author XuJialiang
 * @since 2017-11-16 15:45:12
 * @version V1.0.0
 */
@ClassLevelAnnotation
public class IotHttpClientUtil {
	static Logger LOGGER = LoggerFactory.getLogger(IotHttpClientUtil.class);

	private static final int ERROR_500 = 300500;
	private static final int ERROR_502 = 300502;

	private static final String ERROR_500_DESC = "Internal Server Error.";
	private static final String ERROR_502_DESC = "Connect iot plat failed.";

	public enum Method {
		GET, POST, PUT, DELETE
	}

	/**
	 * APPID
	 */
	private String mAppKey;

	/**
	 * secret
	 */
	private String mAuthorization;

	public IotHttpClientUtil() {
		mAppKey = null;
		mAuthorization = null;
	}

	public IotHttpClientUtil(String appKey, String auth) {
		mAppKey = appKey;
		mAuthorization = auth;
	}

	/**
	 * https request
	 * 
	 * @param url
	 * @param content
	 * @param method
	 * @param contentType
	 * @return
	 */
	@MethodLevelAnnotation
	public JSONObject doPost(String url, String content, Method method,
			String contentType) {
		JSONObject jsonResult = null;
		HttpsURLConnection conn = null;
		OutputStream out = null;
		InputStream in = null;

		try {
			HostnameVerifier hv = new HostnameVerifier() {
				public boolean verify(String urlHostName, SSLSession session) {
					return true;
				}
			};

			HttpsURLConnection.setDefaultHostnameVerifier(hv);

			URL httpUrl = new URL(url);
			conn = (HttpsURLConnection) httpUrl.openConnection();

			conn.setDoOutput(true);
			conn.setDoInput(true);

			conn.setUseCaches(false);
			conn.setRequestMethod(method.name());

			if (null != mAppKey) {
				conn.setRequestProperty("app_key", mAppKey);
			}

			if (null != mAuthorization) {
				conn.setRequestProperty("Authorization", "Bearer "
						+ mAuthorization);
			}

			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "UTF-8");

			byte[] data = null;
			if (null != content && content.length() > 0) {
				data = content.getBytes();

				conn.setRequestProperty("Content-Length",
						String.valueOf(data.length));
			}
			conn.setRequestProperty("Content-Type", contentType);

			conn.setSSLSocketFactory(SslContextFactory.getIotContext()
					.getSocketFactory());
			conn.setInstanceFollowRedirects(false);

			conn.setConnectTimeout(5000);

			conn.connect();

			if (null != data) {
				out = conn.getOutputStream();
				out.write(data);
				out.flush();
			}

			jsonResult = new JSONObject();
			jsonResult.put("code", conn.getResponseCode());

			in = conn.getInputStream();
			if (in.available() > 0) {
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				byte[] buffer = new byte[1024];
				int len;
				while ((len = in.read(buffer)) > -1) {
					baos.write(buffer, 0, len);
				}
				baos.flush();

				JSONObject jsonContent = JSON.parseObject(new String(baos
						.toByteArray(), "UTF-8"));
				jsonResult.put("body", jsonContent);
			} else {
				jsonResult.put("body", null);
			}

		} catch (SocketTimeoutException e) {
			JSONObject body = new JSONObject();
			body.put("error_code", String.valueOf(ERROR_502));
			body.put("error_desc", ERROR_502_DESC);

			jsonResult = new JSONObject();
			jsonResult.put("code", 502);
			jsonResult.put("body", body);

		} catch (Exception e) {
			JSONObject body = new JSONObject();
			body.put("error_code", String.valueOf(ERROR_500));
			body.put("error_desc", ERROR_500_DESC);

			jsonResult = new JSONObject();
			jsonResult.put("code", 500);
			jsonResult.put("body", body);
		} finally {

			if (null != in) {
				try {
					in.close();
				} catch (IOException e1) {
				}
			}

			if (null != out) {
				try {
					out.close();
				} catch (IOException e1) {
				}
			}

			if (null != conn) {
				conn.disconnect();
			}
		}

		return jsonResult;
	}

	/**
	 * http request
	 * 
	 * @param url
	 * @param content
	 * @param method
	 * @param contentType
	 * @return
	 */
	@MethodLevelAnnotation
	public JSONObject doHttpPost(String url, String content, Method method,
			String contentType) {
		JSONObject jsonResult = null;
		HttpURLConnection conn = null;
		OutputStream out = null;
		InputStream in = null;

		try {
			URL httpUrl = new URL(url);
			conn = (HttpURLConnection) httpUrl.openConnection();

			conn.setDoOutput(true);
			conn.setDoInput(true);

			conn.setUseCaches(false);
			conn.setRequestMethod(method.name());

			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "UTF-8");

			byte[] data = null;
			if (null != content && content.length() > 0) {
				data = content.getBytes();

				conn.setRequestProperty("Content-Length",
						String.valueOf(data.length));
			}
			conn.setRequestProperty("Content-Type", contentType);

			conn.setInstanceFollowRedirects(false);

			conn.setConnectTimeout(5000);

			conn.connect();

			if (null != data) {
				out = conn.getOutputStream();
				out.write(data);
				out.flush();
			}

			jsonResult = new JSONObject();
			jsonResult.put("code", conn.getResponseCode());

			in = conn.getInputStream();
			if (in.available() > 0) {
				byte[] result = new byte[in.available()];
				in.read(result);

				JSONObject jsonContent = JSON.parseObject(new String(result));
				jsonResult.put("body", jsonContent);
			} else {
				jsonResult.put("body", null);
			}

		} catch (SocketTimeoutException e) {
			JSONObject body = new JSONObject();
			body.put("error_code", String.valueOf(ERROR_502));
			body.put("error_desc", ERROR_502_DESC);

			jsonResult = new JSONObject();
			jsonResult.put("code", 502);
			jsonResult.put("body", body);

		} catch (Exception e) {
			JSONObject body = new JSONObject();
			body.put("error_code", String.valueOf(ERROR_500));
			body.put("error_desc", ERROR_500_DESC);

			jsonResult = new JSONObject();
			jsonResult.put("code", 500);
			jsonResult.put("body", body);
		} finally {

			if (null != in) {
				try {
					in.close();
				} catch (IOException e1) {
				}
			}

			if (null != out) {
				try {
					out.close();
				} catch (IOException e1) {
				}
			}

			if (null != conn) {
				conn.disconnect();
			}
		}

		return jsonResult;
	}
}
